package com.example.loganalysis.scheduling;

import com.example.loganalysis.dao.TLoginLogDao;
import com.example.loganalysis.dao.TOperateLogDao;
import com.example.loganalysis.dao.TerminalSessionsDao;
import com.example.loganalysis.entity.TLoginLog;
import com.example.loganalysis.entity.TOperateLog;
import com.example.loganalysis.entity.TerminalSession;
import com.example.loganalysis.entity.bo.ChainDataBo;
import com.example.loganalysis.services.IpfsService;
import com.example.loganalysis.services.LoginLogService;
import com.example.loganalysis.services.OperateLogService;
import com.example.loganalysis.services.TerminalSessionService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
public class LogScheduler {

    private static final Logger logger = LoggerFactory.getLogger(LogScheduler.class);
    private final LoginLogService loginLogService;
    private final OperateLogService operateLogService;
    private final TerminalSessionService terminalSessionService;
    private final IpfsService ipfsService;
    private final TOperateLogDao tOperateLogDao;
    private final RestTemplate restTemplate;
    private final TLoginLogDao tLoginLogDao;
    private final TerminalSessionsDao terminalSessionsDao;


    public LogScheduler(LoginLogService loginLogService, TLoginLogDao tLoginLogDao, OperateLogService operateLogService, TerminalSessionService terminalSessionService, IpfsService ipfsService, TOperateLogDao tOperateLogDao, TerminalSessionsDao terminalSessionsDao) {
        this.loginLogService = loginLogService;
        this.tLoginLogDao = tLoginLogDao;
        this.operateLogService = operateLogService;
        this.terminalSessionService = terminalSessionService;
        this.ipfsService = ipfsService;
        this.tOperateLogDao = tOperateLogDao;
        this.terminalSessionsDao = terminalSessionsDao;
        this.restTemplate = new RestTemplate();
    }

    // 每隔 5 分钟执行一次 获取登录日志
    @Scheduled(fixedRate = 300000) // 单位：毫秒
    public void fetchLoginLogs() {
        logger.info("Fetching loginlogs from service...");
        try {
            // 获取所有日志
            List<Map<String, Object>> loginLogs = loginLogService.getLoginLogs();

            if (loginLogs == null || loginLogs.isEmpty()) {
                logger.info("No logs to process.");
                return;
            }

            // 遍历每条日志，并调用 Controller 接口逐条上传
            for (Map<String, Object> log : loginLogs) {
                if (log == null) continue;

                // 构建 TLoginLog 对象
                TLoginLog tLoginLog = new TLoginLog();
                String timeRaw = (String) log.get("datetime");
                if (timeRaw != null) {
                    SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z");
                    SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date parsedDate = inputFormat.parse(timeRaw);
                    tLoginLog.setDateTime(outputFormat.format(parsedDate));
                }

                tLoginLog.setUsername((String) log.get("username"));
                tLoginLog.setIp((String) log.get("ip"));
                tLoginLog.setTypeDisplay((String) log.get("type_display"));
                tLoginLog.setStatusDisplay((String) log.get("status_display"));
                tLoginLog.setLog_type("登录日志");
                tLoginLog.setLog_id((String) log.get("id"));


                // 从日志中获取 id，作为文件名
                String fileName = log.get("id") + ".log"; // 假设日志包含 id 字段
                String logContent = new org.json.JSONObject(log).toString(); // 将日志转为 JSON 字符串

                // 上传日志文件到 IPFS，并设置 IPFS 哈希
                try {
                    String ipfsHash = ipfsService.uploadLogToIpfs(logContent, fileName);
                    tLoginLog.setIpfsHash(ipfsHash);
                } catch (Exception e) {
                    logger.error("Failed to upload log to IPFS: {}", log, e);
                    continue; // 跳过失败的日志
                }

                // 逐条调用 Controller 接口，传递当前的日志
                String url = "http://localhost:8007/api/logs/insertlogin"; // Controller 接口 URL
                restTemplate.postForObject(url, tLoginLog, String.class);

                logger.info("Sent loginlog to controller: {}", tLoginLog);
            }

        } catch (Exception e) {
            logger.error("Error during fetching or sending loginlogs", e);
        }
    }

    // 每隔 5 分钟执行一次 获取操作日志
    @Scheduled(fixedRate = 300000) // 单位：毫秒
    public void fetchOperateLogs() {
        logger.info("Fetching operatelogs from service...");
        try {
            // 获取所有日志
            List<Map<String, Object>> operateLogs = operateLogService.getOperateLogs();

            if (operateLogs == null || operateLogs.isEmpty()) {
                logger.info("No operate logs to process.");
                return;
            }

            // 遍历每条日志，并调用 Controller 接口逐条上传
            for (Map<String, Object> log : operateLogs) {
                if (log == null) continue;

                // 构建 TLoginLog 对象
                TOperateLog tOperateLog = new TOperateLog();
                String timeRaw = (String) log.get("datetime");
                if (timeRaw != null) {
                    SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z");
                    SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date parsedDate = inputFormat.parse(timeRaw);
                    tOperateLog.setDateTime(outputFormat.format(parsedDate));
                }

                tOperateLog.setUsername((String) log.get("user"));
                tOperateLog.setRemoteAddr((String) log.get("remote_addr"));
                tOperateLog.setActionDisplay((String) log.get("action_display"));
                tOperateLog.setResource_type((String) log.get("resource_type"));
                tOperateLog.setLog_type("操作日志");
                tOperateLog.setLog_id((String) log.get("id"));

                // 从日志中获取 id，作为文件名
                String fileName = log.get("id") + ".json"; // 假设日志包含 id 字段
                String logContent = new org.json.JSONObject(log).toString(); // 将日志转为 JSON 字符串

                // 上传日志文件到 IPFS，并设置 IPFS 哈希
                try {
                    String ipfsHash = ipfsService.uploadLogToIpfs(logContent, fileName);
                    tOperateLog.setIpfsHash(ipfsHash);
                } catch (Exception e) {
                    logger.error("Failed to upload operatelog to IPFS: {}", log, e);
                    continue; // 跳过失败的日志
                }

                // 逐条调用 Controller 接口，传递操作日志
                String url = "http://localhost:8007/api/logs/insertoperate"; // Controller 接口 URL
                restTemplate.postForObject(url, tOperateLog, String.class);

                logger.info("Sent operatelog to controller: {}", tOperateLog);
            }

        } catch (Exception e) {
            logger.error("Error during fetching or sending operatelogs", e);
        }
    }

    // 每隔 5 分钟执行一次 获取操作日志
    @Scheduled(fixedRate = 300000) // 单位：毫秒
    public void fetchTerminalSessions() {
        logger.info("Fetching terminalsessions from service...");
        try {
            // 获取所有日志
            List<Map<String, Object>> terminalSessions = terminalSessionService.getTerminalSessions();

            if (terminalSessions == null || terminalSessions.isEmpty()) {
                logger.info("No terminalsession to process.");
                return;
            }

            // 遍历每条日志，并调用 Controller 接口逐条上传
            for (Map<String, Object> log : terminalSessions) {
                if (log == null) continue;

                // 构建 TLoginLog 对象
                TerminalSession terminalSession = new TerminalSession();
                String timeRaw = (String) log.get("date_start");
                if (timeRaw != null) {
                    SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z");
                    SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date parsedDate = inputFormat.parse(timeRaw);
                    terminalSession.setDate_start(outputFormat.format(parsedDate));
                }

                terminalSession.setUser((String) log.get("user"));
                terminalSession.setRemoteAddr((String) log.get("remote_addr"));
                terminalSession.setAsset((String) log.get("asset"));
                terminalSession.setIs_success(String.valueOf(log.get("is_success")));
                terminalSession.setLog_type("终端会话");
                terminalSession.setLog_id((String) log.get("id"));

                String log_id = (String) log.get("id");
                try {
                    // 构造 tar 文件的下载 URL
                    String fileUrl = "http://192.168.231.60/api/v1/terminal/sessions/" + log_id + "/replay/download/";

                    // 构造请求头，添加 Authorization Token
                    HttpHeaders headers = new HttpHeaders();
                    headers.set("Authorization", "Token 3faf3784857fdee03007987e8f41041b4dec6302");

                    // 创建请求实体
                    HttpEntity<Void> requestEntity = new HttpEntity<>(headers);

                    // 使用 RestTemplate 发送 GET 请求
                    ResponseEntity<byte[]> response = restTemplate.exchange(fileUrl, HttpMethod.GET, requestEntity, byte[].class);

                    // 检查响应状态
                    if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                        // 获取文件内容
                        byte[] fileBytes = response.getBody();

                        // 上传 tar 文件到 IPFS
                        try {
                            String ipfsHash = ipfsService.uploadFileToIpfs(fileBytes, log_id + ".tar");
                            terminalSession.setIpfsHash(ipfsHash);
                        } catch (Exception uploadException) {
                            logger.error("Failed to upload tar file to IPFS for log ID {}: {}", log_id, uploadException.getMessage());
                        }
                    } else {
                        logger.error("Failed to download tar file for log ID {}. HTTP status: {}", log_id, response.getStatusCode());
                    }
                } catch (Exception downloadException) {
                    logger.error("Failed to download tar file for log ID {}: {}", log_id, downloadException.getMessage());
                    continue; // 跳过失败的日志
                }


                // 逐条调用 Controller 接口，传递操作日志
                String url = "http://localhost:8007/api/logs/insertTerminalSessions"; // Controller 接口 URL
                restTemplate.postForObject(url, terminalSession, String.class);

                logger.info("Sent terminalsession to controller: {}", terminalSession);
            }

        } catch (Exception e) {
            logger.error("Error during fetching or sending operatelogs", e);
        }
    }

    @Value("${chain.api.url}")
    private String chainApiUrl;

    @Scheduled(fixedRate = 300000) // 单位：毫秒
    public void fetchLoginLogsAndSubmitToChain() {
        logger.info("Fetching login logs...");

        try {
            // 获取登录日志
            List<Map<String, Object>> loginLogs = loginLogService.getLoginLogs();

            if (loginLogs == null || loginLogs.isEmpty()) {
                logger.info("No login logs found.");
                return;
            }

            ObjectMapper objectMapper = new ObjectMapper();
            for (Map<String, Object> log : loginLogs) {
                // 构造 ChainDataBo 对象
                String log_id = (String) log.get("id");
                String ipfsHash = "";
                String ipfsQueryUrl = "http://localhost:8007/api/logs/login_ipfs_hash?log_id=" + log_id; // 替换为实际的 Controller URL
                ResponseEntity<String> response = restTemplate.getForEntity(ipfsQueryUrl, String.class);

                if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                    ipfsHash = response.getBody();
                    System.out.println(ipfsHash);
                }
                String logContent = objectMapper.writeValueAsString(log);
                ChainDataBo chainDataBo = new ChainDataBo();
                chainDataBo.setPrivateKey("376eb95e4a75aa8d01848112f642138581de849ecd78bb41664e040892027f6d");  // 设置私钥
                chainDataBo.setFrom("0x892e3869282b674606a8dabd574c60ec04779d6f");  // 设置 from 地址
                chainDataBo.setContent(logContent);  // 使用日志的 content 字段
                chainDataBo.setLog_type("登录日志");
                chainDataBo.setProcessName("loginlog");  // 设置 processName 为 "loginlog"
                chainDataBo.setIpfs_hash(ipfsHash);  // 从日志获取 IPFS hash

                // 调用 /toChain 接口，将获取的登录日志上链
                String url = chainApiUrl + "/toChain";
                System.out.println(url);
                restTemplate.postForEntity(url, chainDataBo, String.class);

            }
        } catch (Exception e) {
            logger.error("Error fetching or submitting loginlogs to chain", e);
        }
    }

    @Scheduled(fixedRate = 300000) // 单位：毫秒
    public void fetchOperateLogsAndSubmitToChain() {
        logger.info("Fetching login logs...");

        try {
            // 获取操作日志
            List<Map<String, Object>> operateLogs = operateLogService.getOperateLogs();

            if (operateLogs == null || operateLogs.isEmpty()) {
                logger.info("No operate logs found.");
                return;
            }

            ObjectMapper objectMapper = new ObjectMapper();
            for (Map<String, Object> log : operateLogs) {
                // 构造 ChainDataBo 对象
                String log_id = (String) log.get("id");
                String ipfsHash = "";
                String ipfsQueryUrl = "http://localhost:8007/api/logs/operate_ipfs_hash?log_id=" + log_id; // 替换为实际的 Controller URL
                ResponseEntity<String> response = restTemplate.getForEntity(ipfsQueryUrl, String.class);

                if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                    ipfsHash = response.getBody();
                    System.out.println(ipfsHash);
                }

                String logContent = objectMapper.writeValueAsString(log);
                ChainDataBo chainDataBo = new ChainDataBo();
                chainDataBo.setPrivateKey("376eb95e4a75aa8d01848112f642138581de849ecd78bb41664e040892027f6d");  // 设置私钥
                chainDataBo.setFrom("0x892e3869282b674606a8dabd574c60ec04779d6f");  // 设置 from 地址
                chainDataBo.setContent(logContent);  // 使用日志的 content 字段
                chainDataBo.setLog_type("操作日志");
                chainDataBo.setProcessName("operatelog");  // 设置 processName 为 "loginlog"
                chainDataBo.setIpfs_hash(ipfsHash);  // 从日志获取 IPFS hash

                // 调用 /toChain 接口，将获取的登录日志上链
                String url = chainApiUrl + "/toChain";
                restTemplate.postForEntity(url, chainDataBo, String.class);

            }
        } catch (Exception e) {
            logger.error("Error fetching or submitting operatelogs to chain", e);
        }
    }

    @Scheduled(fixedRate = 300000) // 单位：毫秒
    public void fetchTerminalSessionsAndSubmitToChain() {
        logger.info("Fetching terminal sessions...");

        try {

            // 获取终端会话
            List<Map<String, Object>> terminalSessions = terminalSessionService.getTerminalSessions();

            if (terminalSessions == null || terminalSessions.isEmpty()) {
                logger.info("when tochain,No terminalsessions found.");
                return;
            }

            ObjectMapper objectMapper = new ObjectMapper();
            for (Map<String, Object> log : terminalSessions) {
                String log_id = (String) log.get("id");
                String ipfsHash = "";
                String ipfsQueryUrl = "http://localhost:8007/api/logs/terminal_ipfs_hash?log_id=" + log_id; // 替换为实际的 Controller URL
                ResponseEntity<String> response = restTemplate.getForEntity(ipfsQueryUrl, String.class);

                if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                    ipfsHash = response.getBody();
                    System.out.println(ipfsHash);
                }
                // 构造 ChainDataBo 对象
                String logContent = objectMapper.writeValueAsString(log);
                ChainDataBo chainDataBo = new ChainDataBo();
                chainDataBo.setPrivateKey("376eb95e4a75aa8d01848112f642138581de849ecd78bb41664e040892027f6d");  // 设置私钥
                chainDataBo.setFrom("0x892e3869282b674606a8dabd574c60ec04779d6f");  // 设置 from 地址
                chainDataBo.setContent(logContent);  // 使用日志的 content 字段
                chainDataBo.setLog_type("终端会话");
                chainDataBo.setProcessName("terminalsession");  // 设置 processName 为 "loginlog"
                chainDataBo.setIpfs_hash(ipfsHash);

                // 调用 /toChain 接口，将获取的登录日志上链
                String url = chainApiUrl + "/toChain";
                restTemplate.postForEntity(url, chainDataBo, String.class);

            }
        } catch (Exception e) {
            logger.error("Error fetching or submitting terminalsession to chain", e);
        }
    }
}
